
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using Boilen.Freezables;
using Boilen.Guards;


namespace Boilen.Primitives.CodeGeneration
{

#if SL3_0
    using Freezable = DependencyObject;
#endif

    partial class SourceFreezableBase : Freezable,
        INotifyPropertyChanged
#if SL3_0
        ,
        IFreezable
#endif
    {

        private object _privateBackingFieldForProperty_Mutable;


        /// <summary>
        /// Gets or sets test-description-for-mutable.
        /// </summary>
        public object Mutable
        {
            get { return this._privateBackingFieldForProperty_Mutable; }
            set
            {
                this.MutableCoerce(ref value);

                if (!EqualityComparer<object>.Default.Equals(this._privateBackingFieldForProperty_Mutable, value))
                {
                    this.MutableChanging(value);
                    object oldValue = this._privateBackingFieldForProperty_Mutable;
                    this._privateBackingFieldForProperty_Mutable = value;
                    this.MutableChanged(oldValue);
                    this.OnPropertyChanged(MutablePropertyName);
                }
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "Partial method definitions are not required to use method parameters.")]
        partial void MutableCoerce(ref object value);

        [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "Partial method definitions are not required to use method parameters.")]
        partial void MutableChanging(object newValue);

        [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "Partial method definitions are not required to use method parameters.")]
        partial void MutableChanged(object oldValue);


        #region INotifyPropertyChanged Members

        private PropertyChangedEventHandler _privateBackingFieldForEvent_PropertyChanged;

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged
        {
            add { this._privateBackingFieldForEvent_PropertyChanged += value; }
            remove { this._privateBackingFieldForEvent_PropertyChanged -= value; }
        }

        /// <summary>
        /// Raises the <see cref='SourceFreezableBase.PropertyChanged'/> event.
        /// </summary>
        /// <exception cref='System.ArgumentNullException'>
        /// <paramref name='e'/> is <see langword='null'/>.
        /// </exception>
        /// <param name='e'>
        /// An instance of <see cref='PropertyChangedEventArgs'/> that contains the event data.
        /// </param>
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            e.GuardParam("e")
                .NotNull();

            PropertyChangedEventHandler handler = Interlocked.CompareExchange(ref this._privateBackingFieldForEvent_PropertyChanged, null, null);
            if (!object.ReferenceEquals(handler, null))
            {
                handler(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref='SourceFreezableBase.PropertyChanged'/> event.
        /// </summary>
        /// <param name='propertyName'>
        /// The name of the property that changed.
        /// </param>
        [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Supports the PropertyChanged event.")]
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
            this.OnPropertyChanged(e);
        }

        #endregion
        #region Property Names

        /// <summary>
        /// The name of the <see cref='SourceFreezableBase.Mutable'/> property.
        /// </summary>
        public const string MutablePropertyName = "Mutable";

        #endregion
#if SL3_0
        #region IFreezable Members

        private bool _privateBackingFieldForProperty_IsFrozen;
        private EventHandler _privateBackingFieldForEvent_SubpropertyChanged;

        /// <summary>
        /// Gets a value that indicates whether the object is currently modifiable.
        /// </summary>
        /// <returns>
        /// <see langword='true'/> if the object is frozen and cannot be modified; <see langword='false'/> if the object can be modified.
        /// </returns>
        public bool IsFrozen
        {
            get { return this._privateBackingFieldForProperty_IsFrozen; }
        }

        /// <summary>
        /// Occurs when a property changes.
        /// </summary>
        event EventHandler IFreezable.SubpropertyChanged
        {
            add { if (!this.IsFrozen) { this._privateBackingFieldForEvent_SubpropertyChanged += value; } }
            remove { if (!this.IsFrozen) { this._privateBackingFieldForEvent_SubpropertyChanged -= value; } }
        }

        /// <summary>
        /// Makes the current object unmodifiable and sets its <see cref="IsFrozen" /> property to <see langword='true'/>.
        /// </summary>
        public void Freeze()
        {
            if (!this.IsFrozen)
            {
                this.OnFreeze();
                this.FreezeProperties();
                this._privateBackingFieldForEvent_SubpropertyChanged = null;
                this._privateBackingFieldForProperty_IsFrozen = true;
            }
        }

        partial void OnFreeze();

        /// <summary>
        /// Calls <see cref='IFreezable.Freeze'/> on every freezable property.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Implemented as part of SL Freezable pattern.")]
        protected virtual void FreezeProperties()
        {
        }

        /// <summary>
        /// Raises the SubpropertyChanged event.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Supports the SubpropertyChanged event.")]
        protected void OnSubpropertyChanged()
        {
            EventHandler handler = this._privateBackingFieldForEvent_SubpropertyChanged;
            if (!object.ReferenceEquals(handler, null))
            {
                handler(this, EventArgs.Empty);
            }
        }

        #endregion
#else
        #region Freezable Members

        /// <inheritdoc cref='System.Windows.Freezable.CreateInstanceCore'/>
        protected override Freezable CreateInstanceCore()
        {
            return new SourceFreezableBase();
        }

        #endregion
#endif

    }

}
